package com.cmsz.walle.domain.core.impl;

import java.util.ArrayList;
import java.util.List;

import org.apache.curator.framework.CuratorFramework;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.data.Stat;

import com.cmsz.walle.domain.DeployInfo;
import com.cmsz.walle.domain.HostInfo;
import com.cmsz.walle.domain.ModulInfo;
import com.cmsz.walle.domain.SystemInfo;
import com.cmsz.walle.domain.core.Access;
import com.cmsz.walle.domain.core.Constant;

public class AccessImpl implements Access {

	private CuratorFramework zkclient = null;

	public CuratorFramework getZkclient() {
		return zkclient;
	}

	public void setZkclient(CuratorFramework zkclient) {
		this.zkclient = zkclient;
	}

	public void register(HostInfo hostinfo) throws Exception {
		String zkp = Constant.ZKP_HOSTS + "/" + hostinfo.getName();
		Stat s = zkclient.checkExists().forPath(zkp);
		if (s == null) {
			zkclient.create().creatingParentsIfNeeded().forPath(zkp);
			zkclient.create().creatingParentsIfNeeded().forPath(zkp + Constant.ZKP_HOST_NAME, hostinfo.getName().getBytes());
			zkclient.create().creatingParentsIfNeeded().forPath(zkp + Constant.ZKP_HOST_IP, hostinfo.getIp().getBytes());
			zkclient.create().creatingParentsIfNeeded().withMode(CreateMode.EPHEMERAL).forPath(zkp + Constant.ZKP_HOST_LIVING);
		} else {
			Stat s1 = zkclient.checkExists().forPath(zkp + Constant.ZKP_HOST_LIVING);
			assert (s1 == null);
			zkclient.create().creatingParentsIfNeeded().withMode(CreateMode.EPHEMERAL).forPath(zkp + Constant.ZKP_HOST_LIVING);
		}
	}

	public List<HostInfo> getHostsInfo() throws Exception {
		List<String> hosts = zkclient.getChildren().forPath(Constant.ZKP_HOSTS);
		List<HostInfo> hlist = new ArrayList<HostInfo>();
		if (hosts != null) {
			for (String name : hosts) {
				HostInfo inf = new HostInfo();
				inf.setName(name);
				String zkp = Constant.ZKP_HOSTS + "/" + name;
				inf.setIp(new String(zkclient.getData().forPath(zkp + Constant.ZKP_HOST_IP)));
				Stat s1 = zkclient.checkExists().forPath(zkp + Constant.ZKP_HOST_LIVING);
				if (s1 == null) {
					inf.setIsliving(false);
				} else {
					inf.setIsliving(true);
				}
				hlist.add(inf);
			}
		}
		return hlist;
	}

	public void add(SystemInfo systeminfo) throws Exception {
		String zkp = Constant.ZKP_SYSTEMS + "/" + systeminfo.getName();
		Stat s = zkclient.checkExists().forPath(zkp);
		if (s != null) {
			throw new Exception("the system [" + systeminfo.getName() + "] is already exist!");
		}
		zkclient.create().creatingParentsIfNeeded().forPath(zkp + Constant.ZKP_SYSTEM_NAME, systeminfo.getName().getBytes());
		zkclient.create().creatingParentsIfNeeded().forPath(zkp + Constant.ZKP_SYSTEM_DESC, systeminfo.getDesc().getBytes());
	}

	public void update(SystemInfo systeminfo) throws Exception {
		String zkp = Constant.ZKP_SYSTEMS + "/" + systeminfo.getName();
		zkclient.setData().forPath(zkp + Constant.ZKP_SYSTEM_DESC, systeminfo.getDesc().getBytes());
	}

	public List<SystemInfo> getSystemsInfo() throws Exception {
		List<SystemInfo> slist = new ArrayList<SystemInfo>();
		List<String> syss = zkclient.getChildren().forPath(Constant.ZKP_SYSTEMS);
		if (syss != null) {
			for (String sname : syss) {
				SystemInfo sinfo = new SystemInfo();
				String zkp = Constant.ZKP_SYSTEMS + "/" + sname;
				sinfo.setDesc(new String(zkclient.getData().forPath(zkp + Constant.ZKP_SYSTEM_DESC)));
				sinfo.setName(sname);
				sinfo.setModuls(this.getModulsInfo(sname));
				slist.add(sinfo);
			}
		}
		return slist;
	}

	public void add(ModulInfo modulinfo) throws Exception {

		String zkp = Constant.ZKP_SYSTEMS + "/" + modulinfo.getSysname() + "/" + modulinfo.getName();
		Stat s = zkclient.checkExists().forPath(zkp);
		if (s != null) {
			throw new Exception("the modul [" + modulinfo.getName() + "] is already exist!");
		}
		zkclient.create().creatingParentsIfNeeded().forPath(zkp + Constant.ZKP_MODUL_NAME, modulinfo.getName().getBytes());
		zkclient.create().creatingParentsIfNeeded().forPath(zkp + Constant.ZKP_MODUL_STORAGEURL, modulinfo.getStorageurl().getBytes());
		zkclient.create().creatingParentsIfNeeded().forPath(zkp + Constant.ZKP_MODUL_DESC, modulinfo.getDesc().getBytes());
		zkclient.create().creatingParentsIfNeeded().forPath(zkp + Constant.ZKP_MODUL_SYSNAME, modulinfo.getSysname().getBytes());
	}

	public void update(ModulInfo modulinfo) throws Exception {
		String zkp = Constant.ZKP_SYSTEMS + "/" + modulinfo.getSysname() + "/" + modulinfo.getName();
		zkclient.setData().forPath(zkp + Constant.ZKP_MODUL_STORAGEURL, modulinfo.getStorageurl().getBytes());
		zkclient.setData().forPath(zkp + Constant.ZKP_MODUL_DESC, modulinfo.getDesc().getBytes());
	}

	public List<ModulInfo> getModulsInfo(String sysname) throws Exception {
		String zkp = Constant.ZKP_SYSTEMS + "/" + sysname;
		List<ModulInfo> mlist = new ArrayList<ModulInfo>();
		List<String> moduls = zkclient.getChildren().forPath(zkp);
		if (moduls != null) {
			for (String mname : moduls) {
				ModulInfo minfo = new ModulInfo();
				minfo.setName(mname);
				minfo.setDesc(new String(zkclient.getData().forPath(zkp + "/" + mname + Constant.ZKP_MODUL_DESC)));
				minfo.setStorageurl(new String(zkclient.getData().forPath(zkp + "/" + mname + Constant.ZKP_MODUL_STORAGEURL)));
				minfo.setSysname(sysname);
				mlist.add(minfo);
			}
		}
		return mlist;
	}

	public void add(DeployInfo deployinfo) throws Exception {
		String zkp = Constant.ZKP_DEPLOYMENTS + "/" + deployinfo.getModul().getSysname() + "/" + deployinfo.getModul().getName() + "/" + deployinfo.getHost().getName() + Constant.ZKP_DEPLOY_PATHS;
		zkclient.create().creatingParentsIfNeeded().withMode(CreateMode.PERSISTENT_SEQUENTIAL).forPath(zkp + Constant.ZKP_DEPLOY_HOMEPATH, deployinfo.getPath().getBytes());
	}

	public void delete(DeployInfo deployinfo) throws Exception {
		String zkp = Constant.ZKP_DEPLOYMENTS + "/" + deployinfo.getModul().getSysname() + "/" + deployinfo.getModul().getName() + "/" + deployinfo.getHost().getName() + Constant.ZKP_DEPLOY_PATHS;
		List<String> paths = zkclient.getChildren().forPath(zkp);
		if (paths != null) {
			for (String p : paths) {
				String val = new String(zkclient.getData().forPath(zkp + "/" + p));
				if (val == deployinfo.getPath()) {
					zkclient.delete().forPath(zkp + "/" + p);
				}
			}
		}
	}

	public List<DeployInfo> getDeploysInfo() throws Exception {
		List<String> sysnames = zkclient.getChildren().forPath(Constant.ZKP_DEPLOYMENTS);
		List<DeployInfo> dlist = new ArrayList<DeployInfo>();

		if (sysnames != null) {
			for (String sysn : sysnames) {
				List<String> modulnames = zkclient.getChildren().forPath(Constant.ZKP_DEPLOYMENTS + "/" + sysn);
				if (modulnames != null) {
					for (String modn : modulnames) {
						List<String> hostnames = zkclient.getChildren().forPath(Constant.ZKP_DEPLOYMENTS + "/" + sysn + "/" + modn);
						if (hostnames != null) {
							for (String hostn : hostnames) {
								List<String> paths = zkclient.getChildren().forPath(Constant.ZKP_DEPLOYMENTS + "/" + sysn + "/" + modn + "/" + hostn + Constant.ZKP_DEPLOY_PATHS);
								if (paths != null) {
									for (String pathn : paths) {
										DeployInfo dinfo = new DeployInfo();
										String pathval = new String(zkclient.getData().forPath(
												Constant.ZKP_DEPLOYMENTS + "/" + sysn + "/" + modn + "/" + hostn + Constant.ZKP_DEPLOY_PATHS + "/" + pathn));
										dinfo.setPath(pathval);

										HostInfo hinf = new HostInfo();
										hinf.setName(hostn);

										ModulInfo minf = new ModulInfo();
										minf.setName(modn);
										minf.setSysname(sysn);

										dinfo.setHost(hinf);
										dinfo.setModul(minf);
										
										dlist.add(dinfo);
									}

								}
							}
						}
					}
				}
			}
		}
		return dlist;
	}
}
